########################################################################
#  Copyright (C) 2007,8,9 Ehud Ben-Reuven
#  udi@benreuven.com
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation version 2.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
########################################################################
"""ofx2xml OFX-file-name XML-file-name
write OFX v1.02 file in XML format.
You should supply the name of the OFX file to read and the name of the XML file
in which the result will be written to.

OFX v1.02 is written in SGML which is harder to parse than XML
Also OFX v2 are XML based.
Hopefully the same code can be used to parse both the output of this program and OFX v2.

This program verify the HTTP header of an OFX reply remove it and then
transfer the body of the HTTP OFX reply to the execuable osx.exe

osx.exe is assumed to be located in c:\OpenSP
you can download the latest version from http://sourceforge.net/projects/openjade/, http://openjade.sourceforge.net/
(I tried OpenSP-1.5.2-win32.zip)
For a minimal configuration you will need sox.exe and ospXXX.dll

osx.exe needs the definitions (DTD) of OFX supplied from
http://www.ofx.net/DownloadPage/Files/OFX1.0.3.zip
The files are:
ofxact.dtd,ofxbank.dtd,ofxbill.dtd,ofxinv.dtd,ofxmail.dtd,ofxmain.dtd,ofxprof.dtd,ofxsign.dtd
place these files at c:\OpenSP
"""

import sys, os, string
import subprocess

def ofx2xml(ofxfile,outfile):
    if not os.path.exists(ofxfile):
        print "\nFile %s not found." % (ofxfile)
        raise Exception('File not found')

    fofx=open(ofxfile,'r')
    lofx=fofx.readlines()
    fofx.close()

    # Skip everything before <OFX>
    scanner_output = []
    in_ofx = False
    for l in lofx:
        l = l.replace('&amp;','&#38;')
        if in_ofx:
            scanner_output.append(l)
        elif l.find('<OFX>') != -1:
            scanner_output.append(l)
            in_ofx = True
    
    if os.path.exists('c:/OpenSP'):
        popen_args = 'c:/OpenSP/osx.exe -D c:\\OpenSP -wno-valid ofxmain.dtd -'
    else:
        popen_args = ['osx',  '-wno-valid', 'ofxmain.dtd', '-']

    if isinstance(outfile,basestring):
        xml_file = open(outfile, 'w')
    else:
        tmpfile=ofxfile+'.xml'        
        xml_file = open(tmpfile, 'w')
    p = subprocess.Popen(popen_args,
                         stdin=subprocess.PIPE, stdout=xml_file,
                         stderr=subprocess.PIPE)
    (out, err) = p.communicate(input=''.join(scanner_output))
    if p.returncode != 0:
        if out:
            print "osx stdout:\n" + out
        if err:
            print "osx stderr:\n" + err
        raise Exception("Unexpected return code %d from osx" % p.returncode)
    xml_file.close()
    if not isinstance(outfile,basestring):
        xml_file=open(tmpfile,'r')
        for line in xml_file:
            outfile.write(line)
        xml_file.close()
        os.remove(tmpfile)

if __name__ == "__main__":
    if len(sys.argv) < 3:
        print "ofx2xml <OFX-file> <XML-file>"
        sys.exit(1)
    
    ofxfile = sys.argv[1]
    xmlfile = sys.argv[2]
    ofx2xml(ofxfile,xmlfile)
